/* hc128.c
** 
** Copyright (c) 2007, Matt Hamrick, Siobhan Murtagh & Damon Orecks
** All rights reserved.
** 
** Redistribution  and  use  in  source  and  binary  forms,  with  or  without
** modification, are permitted provided that the following conditions are met:
** 
**  * Redistributions of  source code must  retain the above  copyright notice,
**    this list of conditions and the following disclaimer.
** 
**  * Redistributions in binary form must reproduce the above copyright notice,
**    this list of conditions and the following disclaimer in the documentation
**    and/or other materials provided with the distribution.
** 
**  * Neither  the  name  of the  DangerThink  Project  nor  the names  of  its
**    contributors may be used to endorse or promote products derived from this
**    software without specific prior written permission.
** 
** THIS SOFTWARE IS PROVIDED BY  THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY  EXPRESS OR IMPLIED WARRANTIES,  INCLUDING, BUT NOT  LIMITED TO, THE
** IMPLIED WARRANTIES  OF MERCHANTABILITY AND FITNESS FOR  A PARTICULAR PURPOSE
** ARE DISCLAIMED.  IN NO  EVENT SHALL THE  COPYRIGHT OWNER OR  CONTRIBUTORS BE
** LIABLE  FOR  ANY  DIRECT,   INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR
** CONSEQUENTIAL  DAMAGES  (INCLUDING,  BUT  NOT  LIMITED  TO,  PROCUREMENT  OF
** SUBSTITUTE GOODS  OR SERVICES;  LOSS OF USE,  DATA, OR PROFITS;  OR BUSINESS
** INTERRUPTION)  HOWEVER CAUSED  AND ON  ANY THEORY  OF LIABILITY,  WHETHER IN
** CONTRACT,  STRICT LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE OR  OTHERWISE)
** ARISING IN ANY WAY  OUT OF THE USE OF THIS SOFTWARE,  EVEN IF ADVISED OF THE
** POSSIBILITY OF SUCH DAMAGE.
**
** $Id: hc128.c 15 2007-05-11 05:36:17Z matthew.hamrick $
*/

/* Macro Definitions */

/* File Includes */
#include "hc128.h"
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/types.h>

/* Static Function Prototypes */
static void hc128_advance( hc128 *cipher );

/* Function Definitions */

DTErr hc128_new( hc128 **cipher ) {
  DTErr err = DT_E_NOERR;
  u_int32_t deallocate = 0;

  do {
    if( NULL == cipher ) {
      err = DT_E_BADPARAMS;
      break;
    }
    
    if( NULL == *cipher ) {
      if( NULL == ( *cipher = malloc( sizeof( hc128 ) ) ) ) {
	err = DT_E_MALLOC;
	break;
      }
    }

    deallocate = 1;

    if( DT_E_NOERR != ( err = hc128_clear( cipher ) ) ) {
      break;
    }

  } while( 0 );

  if( ( err != DT_E_NOERR ) && ( deallocate != 0 ) ) {
    free( *cipher );
  }

  return( err );
}

DTErr hc128_delete( hc128 *cipher ) {
  DTErr err = DT_E_NOERR;

  do {

    /* note: We depend on hc128_clear()'s  checking for a null cipher pointer */
    /* here. We should be careful to remove null checking from hc128_clear as */
    /* we depend on it elsewhere in the code.                                 */

    if( DT_E_NOERR != (err = hc128_clear( cipher ) ) ) {
      break;
    }

    free( cipher );

  } while( 0 );

  return( err );
}

DTErr hc128_key( hc128 *cipher, char *key ) {
  DTErr err = DT_E_NOERR;

  do {
    if( NULL == cipher ) {
      err = DT_E_BADPARAMS;
      break;
    }

    if( NULL == key ) {
      err = DT_E_BADPARAMS;
      break;
    }

  } while( 0 );

  return( err );
}

DTErr hc128_iv( hc128 *cipher, char *iv ) {
  DTErr err = DT_E_NOERR;

  do {
    if( NULL == cipher ) {
      err = DT_E_BADPARAMS;
      break;
    }

    if( NULL == iv ) {
      err = DT_E_BADPARAMS;
      break;
    }

  } while( 0 );

  return( err );
}

DTErr hc128_init( hc128 *cipher ) {
  DTErr err = DT_E_NOERR;

  do {
    if( NULL == cipher ) {
      err = DT_E_BADPARAMS;
      break;
    }

  } while( 0 );

  return( err );
}

DTErr hc128_keystream( hc128 *cipher, char *output, unsigned int length, unsigned int *bytes_written ) {
  DTErr err = DT_E_NOERR;

  do {
    if( NULL == cipher ) {
      err = DT_E_BADPARAMS;
      break;
    }

    if( NULL == output ) {
      err = DT_E_BADPARAMS;
      break;
    }

    if( NULL != bytes_written ) {
      bytes_written = length;
    }

  } while( 0 );

  return( err );
}

DTErr hc128_encrypt( hc128 *cipher, char *input, unsigned int input_length, char *output, unsigned int output_length, unsigned int *bytes_written ) {
  DTErr err = DT_E_NOERR;
  unsigned int length;

  do {
    if( NULL == cipher ) {
      err = DT_E_BADPARAMS;
      break;
    }

    if( NULL == output ) {
      err = DT_E_BADPARAMS;
      break;
    }

    if( NULL == input ) {
      err = DT_E_BADPARAMS;
      break;
    }

    if( output_length < input_length ) {
      length = output_length;
    } else {
      length = input_length;
    }

    if( NULL != bytes_written ) {
      bytes_written = length;
    }

  } while( 0 );

  return( err );
}

DTErr hc128_decrypt( hc128 *cipher, char *input, unsigned int input_length, char *output, unsigned int output_length, unsigned int *bytes_written ) {

  /* note: As  it turns  out, with many  stream ciphers, encryption  is the */
  /* same operation  as decryption. Rather  than duplicate the  code above, */
  /* we're simply calling it.                                               */
  
  return( hc128_encrypt( cipher, input, input_length, output, output_length, bytes_written ) );

}

DTErr hc128_seek( hc128 *cipher, DTSeekMode mode, int offset ) {
  DTErr err = DT_E_NOERR;

  do {
    if( NULL == cipher ) {
      err = DT_E_BADPARAMS;
      break;
    }

  } while( 0 );

  return( err );
}

DTErr hc128_clear( hc128 *cipher ) {
  DTErr err = DT_E_NOERR;

  do {

    /*  note:  you're  probably  motivated  to  remove  the  following  NULL */
    /*  checking code in the  interests of efficiency. Please note, however, */
    /*  that   other   functions    (notably   hc128_delete()   depends   on */
    /*  hc128_clear()  parameter checking. Remember,  the contract  is, that */
    /*  any function that  shows up in the hc128.h  interface does parameter */
    /*  checking for manditory arguments.                                    */

    if( NULL == cipher ) {
      err = DT_E_BADPARAMS;
      break;
    }

    memset( cipher, 0, sizeof( hc128 ) );

  } while( 0 );

  return( err );
}

static void hc128_advance( hc128 *cipher ) {
}
